return function(BOXUI)

local utils = BOXUI.utils

local colorWhite = {1, 1, 1}

local int = utils.int
local max = utils.max
local clamp = utils.clamp


local ListContent = utils.newclass("list_content")
local lcmt = ListContent

ListContent.template_theme =  {
	itemHeight = 32, itemPadVert = 8, itemPadHori = 8,
	itemBack   = {0, 0, 1},
	itemFore   = {0, 1, 0}, itemForeActive = {1, 1, 0},
}

ListContent.init = function(self, x, y, width, height)
	self.theme = BOXUI.theme
	self.x, self.y = x, y
	self.width, self.height = width, height
	
	self.items = nil
	self.itemActive = nil
	self.itemSelected = nil
	self.onClick = nil
	self.font = love.graphics.getFont()
	
	self.canvas = love.graphics.newCanvas(width, height)
	--self.canvas:setWrap("clampzero", "clampzero")
	self.quad = love.graphics.newQuad(0, 0, width, height, width, height)
end

ListContent.insert = function(self, text, context, refresh)
	local entry = {text = text, context = context}
	if not self.items then self.items = {} end
	table.insert(self.items, entry)
	if refresh == true then self:refresh() end
end

ListContent.setItems = function(self, t, refresh)
	self.items = t
	if refresh == true then self:refresh() end
end

ListContent.selectActiveItem = function(self, x, y)
	x, y = x - self.x, y - self.y
	if not self.items then return end
	local prevActive = self.itemActive
	local active = nil

	local theme = self.theme
	local height  = theme.itemHeight
	local advance = height + theme.itemPadVert
	local relY = y % advance
	
	if relY >= 0 and relY < height then
		active = 1 + int(y / advance)
		if active < 1 or active > #self.items then active = nil end
	end

	self.itemActive = active
	if prevActive ~= active then
		return true
	end
end

ListContent.unfocus = function(self)
	self.itemActive = nil
end

ListContent.focus = function(self)
end

ListContent.mousemoved = function(self, x, y, dx, dy)
	self:selectActiveItem(x, y)
end

ListContent.mousepressed = function(self, x, y, button)
	if button ~= 1 then return end
	self.itemSelected = self.itemActive
end

ListContent.mousereleased = function(self, x, y, button)
	local selected, active = self.itemSelected, self.itemActive
	if button ~= 1 then return end
	if selected == nil then self:selectActiveItem(x, y) return end
	
	self.itemSelected = nil
	--self.itemActive = nil
	local item = self.items[selected]
	
	if selected == active then
		if item and self.onClick then
			self.onClick(item)
		end
	end
end

local lineWidth = function(font, text, icon, pad)
	local texttype = type(text)
	local w = icon and (icon:getWidth() + pad) or 0
	if texttype == "string" then
		w = w + font:getWidth(text)
	elseif texttype == "table" then
		for i = 2, #text, 2 do w = w + font:getWidth(text[i]) end
	end
	
	return w
end

ListContent.getLineWidth = function(self)
	local theme = self.theme
	local font = self.font
	local itemph = theme.itemPadHori
	local width = 0
	for i, v in ipairs(self.items) do
		width = max(width, lineWidth(font, v.text, v.icon, itemph))
	end
	return width + 2 * itemph
end

-- create a new canvas if required, return canvas size
ListContent.fitCanvas = function(self)
	local selfw, selfh = self.width, self.height
	local canvas = self.canvas
	if not canvas then return selfw, selfh end
	
	local width, height = canvas:getDimensions()
	if selfw <= width and selfh <= height then return width, height end
	canvas:release()
	self.canvas = love.graphics.newCanvas(selfw, selfh)
	return selfw, selfh
end

ListContent.refresh = function(self, redraw)
	self.itemActive = nil
	self.itemSelected = nil

	local numitems = self.items and #self.items or 0
	local theme = self.theme
	
	
	if numitems == 0 then
		--self.canvas:renderTo(love.graphics.clear)
		self.width, self.height = theme.itemPadHori, theme.itemPadVert
		--self.overlay:renderTo(love.graphics.clear)
		return
	end
	
	local itemh = theme.itemHeight
	local itempv = theme.itemPadVert
	local itemph = theme.itemPadHori
	
	self.height = itemh * numitems + itempv * (numitems - 1)
	
	self.width = self:getLineWidth()

	
	self:fitCanvas()
	
	self.drawPassive = theme.draw.listContentPassive
	if redraw then self:redraw() end
end

ListContent.expand = function(self, width, height)
	if self.width < width then self.width = width end
	self:fitCanvas()
end



ListContent.redraw = function(self)
	local canvas = self.canvas
	if not canvas then return end

	love.graphics.setCanvas(canvas)
	love.graphics.clear()
	self:drawPassive(0, 0)
	love.graphics.setCanvas()
end

ListContent.updateViewport = function(self, vpx, vpy, vpw, vph)
	local canvas = self.canvas
	local width, height
	if self.canvas then width, height = canvas:getDimensions()
	else width, height = self.width, self.height end
	self.quad:setViewport(vpx, vpy, vpw, vph, width, height)
end

ListContent.draw = function(self, x, y)
	x, y = self.x + (x or 0), self.y + (y or 0)
	if self.canvas then
		love.graphics.setColor(colorWhite)
		love.graphics.draw(self.canvas, self.quad, x, y)
	else
		local vpx, vpy, vpw, vph = self.quad:getViewport()
		self:drawPassive(x - vpx, y - vpy, vpy, vpy + vph) -- not a typo; y = l1, l2
	end
end

BOXUI.add(ListContent)

local Container = BOXUI.container
local M = utils.newclass("list", Container)

--utils.freshenprops(M.template_theme, default_theme)

--local create = M.create

M.init = function(self, x, y, width, height)
	Container.init(self, x, y, width, height)
	self.wrapHori = false
	self.wrapVert = false

	local list = ListContent.new(0,0, 10, 10)
	
	self.content = list
	self.list = list -- alias
end

M.insert = function(self, text, context, refresh)
	self.content:insert(text, context)
	if refresh == true then self:refresh(true) end
end

M.setItems = function(self, t, refresh)
	self.content:setItems(t)
	if refresh == true then self:refresh(true) end
end

M.refresh = function(self, redraw)
	Container.refresh(self, redraw)
	self.drawOverlay = self.theme.draw.listOverlay
end


BOXUI.add(M)
end

